﻿
namespace Patterns4Net.Core
{
    using System;
    using System.Collections.Generic;
    using System.Linq;

    public static class EnumerableExtensions
    {
        public static bool None<T>(this IEnumerable<T> items, Func<T, bool> predicate)
        {
            return items.Any(predicate) == false;
        }

        public static bool None<T>(this IEnumerable<T> items, Func<T, int, bool> predicate)
        {
            return items.Where(predicate).Count() == 0;
        }

        public static IEnumerable<T> Concat<T>(this IEnumerable<T> items, T item)
        {
            return items.Concat(new[] { item });
        }

        public static bool All<T>(this IEnumerable<T> items, Func<T, int, bool> predicate)
        {
            return items.Where(predicate).Count() == items.Count();
        }

        public static bool IsEmpty<T>(this IEnumerable<T> items)
        {
            return items.Any() == false;
        }

        public static void ForEach<T>(this IEnumerable<T> items, Action<T> action)
        {
            foreach (var item in items.ToArray())
            {
                action(item);
            }
        }

        public static IEnumerable<T> Distinct<T>(this IEnumerable<T> items, Func<T, T, bool> areEqual)
        {
            return items.Distinct(new LambdaComparer<T>(areEqual));
        }

        private class LambdaComparer<T> : IEqualityComparer<T>
        {
            private readonly Func<T, T, bool> areEqual;

            public LambdaComparer(Func<T, T, bool> areEqual)
            {
                this.areEqual = areEqual;
            }

            public bool Equals(T x, T y)
            {
                return this.areEqual(x, y);
            }

            public int GetHashCode(T obj)
            {
                // we have to return constant hash-code, because we don't know what is and what isn't equal...
                return 0;   
            }
        }
    }
}
